#!/usr/bin/env python3
"""
游戏AI按键回放系统
基于录制的JSON数据自动回放按键事件，支持多种回放模式和精准时间控制
"""

import json
import time
import argparse
import sys
import os
from datetime import datetime
from pathlib import Path
import pyautogui
import win32api, win32con
import ctypes
from ctypes import wintypes
import threading

# 禁用pyautogui的保护机制
pyautogui.FAILSAFE = False
pyautogui.PAUSE = 0

class GameReplayer:
    def __init__(self, json_file_path, speed_multiplier=1.0, target_window=None):
        """
        初始化游戏回放器
        
        Args:
            json_file_path: 录制数据的JSON文件路径
            speed_multiplier: 回放速度倍数 (1.0=原速, 2.0=2倍速, 0.5=半速)
            target_window: 目标窗口标题 (可选)
        """
        self.json_file_path = json_file_path
        self.speed_multiplier = speed_multiplier
        self.target_window = target_window
        self.events = []
        self.recording_info = {}
        self.is_playing = False
        self.is_paused = False
        self.start_time = None
        
        # Windows键盘输入相关
        self.user32 = ctypes.windll.user32
        self.kernel32 = ctypes.windll.kernel32
        
        # VK键码映射
        self.vk_map = {
            'W': 0x57, 'A': 0x41, 'S': 0x53, 'D': 0x44,
            'SPACE': 0x20, 'SHIFT': 0x10, 'CTRL': 0x11, 'ALT': 0x12,
            'ESC': 0x1B, 'ENTER': 0x0D, 'TAB': 0x09,
            'F1': 0x70, 'F2': 0x71, 'F3': 0x72, 'F4': 0x73,
            'Q': 0x51, 'E': 0x45, 'R': 0x52, 'T': 0x54,
            'Y': 0x59, 'U': 0x55, 'I': 0x49, 'O': 0x4F, 'P': 0x50,
            'F': 0x46, 'G': 0x47, 'H': 0x48, 'J': 0x4A, 'K': 0x4B, 'L': 0x4C,
            'Z': 0x5A, 'X': 0x58, 'C': 0x43, 'V': 0x56, 'B': 0x42, 'N': 0x4E, 'M': 0x4D,
            '1': 0x31, '2': 0x32, '3': 0x33, '4': 0x34, '5': 0x35,
            '6': 0x36, '7': 0x37, '8': 0x38, '9': 0x39, '0': 0x30
        }
        
        self.load_recording_data()
    
    def load_recording_data(self):
        """加载录制数据"""
        try:
            with open(self.json_file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            self.recording_info = data.get('recording_info', {})
            self.events = data.get('events', [])
            
            print(f"✅ 成功加载录制数据:")
            print(f"   📁 文件: {self.json_file_path}")
            print(f"   ⏱️  录制时长: {self.recording_info.get('total_duration', 0):.2f}秒")
            print(f"   🎯 事件总数: {len(self.events)}")
            print(f"   📊 按键事件: {data.get('statistics', {}).get('keyboard_events', 0)}")
            print(f"   🖱️  鼠标事件: {data.get('statistics', {}).get('mouse_events', 0)}")
            
            # 显示原始窗口信息
            window_info = self.recording_info.get('window_info', {})
            if window_info:
                print(f"   🎮 原始窗口: {window_info.get('title', 'Unknown')}")
            
        except Exception as e:
            print(f"❌ 加载录制数据失败: {e}")
            sys.exit(1)
    
    def send_key_input(self, key_name, action):
        """发送键盘输入"""
        if key_name not in self.vk_map:
            print(f"⚠️  不支持的按键: {key_name}")
            return False
        
        vk_code = self.vk_map[key_name]
        
        try:
            if action == 'down':
                # 按键按下
                self.user32.keybd_event(vk_code, 0, 0, 0)
            elif action == 'up':
                # 按键释放
                self.user32.keybd_event(vk_code, 0, win32con.KEYEVENTF_KEYUP, 0)
            
            return True
            
        except Exception as e:
            print(f"❌ 按键输入失败 {key_name}-{action}: {e}")
            return False
    
    def send_mouse_input(self, event):
        """发送鼠标输入"""
        try:
            x, y = event.get('x', 0), event.get('y', 0)
            action = event.get('action', '')
            
            if action == 'move':
                # 鼠标移动
                pyautogui.moveTo(x, y, duration=0)
            
            elif action == 'left_down':
                # 鼠标左键按下
                pyautogui.mouseDown(x, y, button='left')
            
            elif action == 'left_up':
                # 鼠标左键释放
                pyautogui.mouseUp(x, y, button='left')
            
            elif action == 'right_down':
                # 鼠标右键按下
                pyautogui.mouseDown(x, y, button='right')
            
            elif action == 'right_up':
                # 鼠标右键释放
                pyautogui.mouseUp(x, y, button='right')
            
            return True
            
        except Exception as e:
            print(f"❌ 鼠标输入失败: {e}")
            return False
    
    def analyze_timing_patterns(self):
        """分析时间模式和按键节奏"""
        if not self.events:
            return
        
        keyboard_events = [e for e in self.events if e.get('type') == 'keyboard']
        if len(keyboard_events) < 2:
            return
        
        print("\n⏱️  时间模式分析:")
        print("=" * 50)
        
        # 分析按键间隔
        intervals = []
        key_durations = {}
        
        for i in range(1, len(keyboard_events)):
            prev_event = keyboard_events[i-1]
            curr_event = keyboard_events[i]
            
            interval = curr_event.get('timestamp', 0) - prev_event.get('timestamp', 0)
            intervals.append(interval)
            
            # 计算按键持续时间
            if prev_event.get('action') == 'down' and curr_event.get('action') == 'up':
                if prev_event.get('key_name') == curr_event.get('key_name'):
                    key_name = prev_event.get('key_name')
                    duration = interval
                    if key_name not in key_durations:
                        key_durations[key_name] = []
                    key_durations[key_name].append(duration)
        
        if intervals:
            avg_interval = sum(intervals) / len(intervals)
            min_interval = min(intervals)
            max_interval = max(intervals)
            
            print(f"按键间隔统计:")
            print(f"  平均间隔: {avg_interval:.3f}秒")
            print(f"  最小间隔: {min_interval:.3f}秒")
            print(f"  最大间隔: {max_interval:.3f}秒")
        
        if key_durations:
            print(f"\n按键持续时间:")
            for key_name, durations in key_durations.items():
                if durations:
                    avg_duration = sum(durations) / len(durations)
                    print(f"  {key_name}: {avg_duration:.3f}秒 (平均)")
    
    def get_realistic_timing(self, current_timestamp, next_timestamp):
        """
        获取真实的时间间隔，考虑录制时的实际节奏
        """
        time_diff = next_timestamp - current_timestamp
        
        # 应用速度倍数
        adjusted_time = time_diff / self.speed_multiplier
        
        # 设置合理的时间范围
        if adjusted_time < 0.001:  # 最小1ms
            return 0.001
        elif adjusted_time > 5.0:  # 最大5秒，避免过长等待
            return 5.0
        else:
            return adjusted_time
    
    def replay_events(self, event_types=None, skip_mouse_moves=True):
        """
        回放事件
        
        Args:
            event_types: 要回放的事件类型列表 ['keyboard', 'mouse']
            skip_mouse_moves: 是否跳过鼠标移动事件
        """
        if not self.events:
            print("❌ 没有可回放的事件")
            return
        
        if event_types is None:
            event_types = ['keyboard', 'mouse']
        
        print(f"\n🎮 开始回放游戏操作...")
        print(f"   ⚡ 回放速度: {self.speed_multiplier}x")
        print(f"   🎯 事件类型: {', '.join(event_types)}")
        print(f"   ⏱️  原始时长: {self.recording_info.get('total_duration', 0):.2f}秒")
        print(f"   📊 显示格式: [实际时间|原始时间] 事件")
        print(f"   ⏸️  控制: 按 'P' 暂停/继续, 按 'Q' 停止")
        print("=" * 50)
        
        self.is_playing = True
        self.start_time = time.time()
        
        # 启动键盘控制监听
        control_thread = threading.Thread(target=self.keyboard_control_listener, daemon=True)
        control_thread.start()
        
        previous_timestamp = 0
        keyboard_states = {}  # 跟踪键盘状态
        
        try:
            for i, event in enumerate(self.events):
                if not self.is_playing:
                    break
                
                # 暂停检查
                while self.is_paused and self.is_playing:
                    time.sleep(0.01)
                
                event_type = event.get('type', '')
                timestamp = event.get('timestamp', 0)
                
                # 跳过不需要的事件类型
                if event_type not in event_types:
                    continue
                
                # 跳过鼠标移动事件 (可选)
                if skip_mouse_moves and event_type == 'mouse' and event.get('action') == 'move':
                    continue
                
                # 等待到事件时间 (使用真实录制节奏)
                if i > 0:  # 跳过第一个事件
                    wait_time = self.get_realistic_timing(previous_timestamp, timestamp)
                    
                    # 支持暂停功能
                    while self.is_paused and self.is_playing:
                        time.sleep(0.01)
                    
                    if self.is_playing:  # 确保没有被停止
                        time.sleep(wait_time)
                
                # 执行事件
                success = False
                if event_type == 'keyboard':
                    key_name = event.get('key_name', '')
                    action = event.get('action', '')
                    
                    # 防止重复按键状态
                    key_state = keyboard_states.get(key_name, 'up')
                    if action == key_state:
                        continue  # 跳过重复状态
                    
                    success = self.send_key_input(key_name, action)
                    if success:
                        keyboard_states[key_name] = action
                        elapsed = time.time() - self.start_time
                        original_time = timestamp
                        # 显示原始时间戳和实际经过时间
                        print(f"⌨️  [{elapsed:6.2f}s|{original_time:6.2f}s] {key_name} {action}")
                
                elif event_type == 'mouse':
                    action = event.get('action', '')
                    x, y = event.get('x', 0), event.get('y', 0)
                    success = self.send_mouse_input(event)
                    if success:
                        elapsed = time.time() - self.start_time
                        original_time = timestamp
                        print(f"🖱️  [{elapsed:6.2f}s|{original_time:6.2f}s] {action} at ({x}, {y})")
                
                previous_timestamp = timestamp
                
                # 显示进度 (每50个事件)
                if (i + 1) % 50 == 0:
                    progress = (i + 1) / len(self.events) * 100
                    elapsed = time.time() - self.start_time
                    print(f"📊 进度: {progress:.1f}% ({i+1}/{len(self.events)}) - {elapsed:.1f}s")
        
        except KeyboardInterrupt:
            print("\n⚠️  用户中断回放")
        
        finally:
            self.is_playing = False
            
            # 释放所有按下的键
            for key_name, state in keyboard_states.items():
                if state == 'down':
                    self.send_key_input(key_name, 'up')
                    print(f"🔓 释放按键: {key_name}")
            
            total_time = time.time() - self.start_time
            print(f"\n✅ 回放完成，耗时: {total_time:.2f}秒")
    
    def keyboard_control_listener(self):
        """监听键盘控制指令"""
        while self.is_playing:
            try:
                # 检查P键 (暂停/继续)
                if win32api.GetAsyncKeyState(0x50) & 0x8000:  # P键
                    if not self.is_paused:
                        self.is_paused = True
                        print("\n⏸️  回放已暂停 (按P继续)")
                    else:
                        self.is_paused = False
                        print("▶️  回放已继续")
                    time.sleep(0.5)  # 防止重复触发
                
                # 检查Q键 (停止)
                if win32api.GetAsyncKeyState(0x51) & 0x8000:  # Q键
                    print("\n🛑 用户停止回放")
                    self.is_playing = False
                    break
                
                time.sleep(0.01)
            except:
                break
    
    def analyze_events(self):
        """分析事件模式"""
        if not self.events:
            return
        
        print("\n📊 事件分析报告:")
        print("=" * 50)
        
        # 统计各类事件
        event_stats = {}
        key_stats = {}
        mouse_stats = {}
        
        for event in self.events:
            event_type = event.get('type', '')
            event_stats[event_type] = event_stats.get(event_type, 0) + 1
            
            if event_type == 'keyboard':
                key_name = event.get('key_name', '')
                key_stats[key_name] = key_stats.get(key_name, 0) + 1
            
            elif event_type == 'mouse':
                action = event.get('action', '')
                mouse_stats[action] = mouse_stats.get(action, 0) + 1
        
        # 显示统计
        print("事件类型分布:")
        for event_type, count in sorted(event_stats.items()):
            print(f"  {event_type}: {count}")
        
        if key_stats:
            print("\n按键使用频率 (前10):")
            sorted_keys = sorted(key_stats.items(), key=lambda x: x[1], reverse=True)[:10]
            for key, count in sorted_keys:
                print(f"  {key}: {count}")
        
        if mouse_stats:
            print("\n鼠标操作分布:")
            for action, count in sorted(mouse_stats.items()):
                print(f"  {action}: {count}")
        
        # 添加时间模式分析
        self.analyze_timing_patterns()
    
    def extract_key_sequence(self, output_file=None):
        """提取按键序列用于模式分析"""
        keyboard_events = [e for e in self.events if e.get('type') == 'keyboard']
        
        if not keyboard_events:
            print("❌ 没有找到键盘事件")
            return
        
        # 提取按键序列
        key_sequence = []
        for event in keyboard_events:
            if event.get('action') == 'down':  # 只记录按下事件
                key_sequence.append(event.get('key_name', ''))
        
        sequence_str = ''.join(key_sequence)
        
        print(f"\n🔤 按键序列 (长度: {len(sequence_str)}):")
        print(f"   {sequence_str}")
        
        if output_file:
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write(sequence_str)
            print(f"   💾 已保存到: {output_file}")
        
        return sequence_str

def find_json_files(directory):
    """查找目录下的JSON文件"""
    json_files = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith('.json') and 'keystrokes' in file:
                json_files.append(os.path.join(root, file))
    return json_files

def main():
    parser = argparse.ArgumentParser(description="游戏AI按键回放系统")
    parser.add_argument('--file', '-f', type=str, help='JSON录制文件路径')
    parser.add_argument('--speed', '-s', type=float, default=1.0, help='回放速度倍数 (默认1.0)')
    parser.add_argument('--window', '-w', type=str, help='目标窗口标题')
    parser.add_argument('--analyze', '-a', action='store_true', help='分析事件模式')
    parser.add_argument('--keyboard-only', '-k', action='store_true', help='只回放键盘事件')
    parser.add_argument('--mouse-only', '-m', action='store_true', help='只回放鼠标事件')
    parser.add_argument('--include-mouse-moves', action='store_true', help='包含鼠标移动事件')
    parser.add_argument('--extract-keys', '-e', type=str, help='提取按键序列到文件')
    parser.add_argument('--list', '-l', action='store_true', help='列出可用的录制文件')
    
    args = parser.parse_args()
    
    # 列出可用文件
    if args.list:
        print("🔍 搜索录制文件...")
        json_files = find_json_files('pictures')
        if json_files:
            print(f"找到 {len(json_files)} 个录制文件:")
            for i, file in enumerate(json_files, 1):
                # 获取文件信息
                try:
                    with open(file, 'r', encoding='utf-8') as f:
                        data = json.load(f)
                    info = data.get('recording_info', {})
                    duration = info.get('total_duration', 0)
                    window_title = info.get('window_info', {}).get('title', 'Unknown')
                    event_count = len(data.get('events', []))
                    recorded_at = info.get('recorded_at', 'Unknown')
                    
                    print(f"  {i}. {file}")
                    print(f"     🎮 窗口: {window_title}")
                    print(f"     ⏱️  时长: {duration:.1f}秒")
                    print(f"     📊 事件: {event_count}")
                    print(f"     📅 录制: {recorded_at}")
                except:
                    print(f"  {i}. {file} (无法读取详情)")
        else:
            print("❌ 未找到录制文件")
        return
    
    # 检查文件参数
    if not args.file:
        print("❌ 请指定JSON录制文件路径")
        print("使用 --list 查看可用文件，或用 --file 指定文件路径")
        return
    
    if not os.path.exists(args.file):
        print(f"❌ 文件不存在: {args.file}")
        return
    
    # 创建回放器
    replayer = GameReplayer(args.file, args.speed, args.window)
    
    # 分析模式
    if args.analyze:
        replayer.analyze_events()
        if args.extract_keys:
            replayer.extract_key_sequence(args.extract_keys)
        return
    
    # 提取按键序列
    if args.extract_keys:
        replayer.extract_key_sequence(args.extract_keys)
        return
    
    # 确定事件类型
    event_types = []
    if args.keyboard_only:
        event_types = ['keyboard']
    elif args.mouse_only:
        event_types = ['mouse']
    else:
        event_types = ['keyboard', 'mouse']
    
    # 确认开始回放
    print(f"\n⚠️  准备开始回放到游戏...")
    print(f"   📁 文件: {args.file}")
    print(f"   ⚡ 速度: {args.speed}x")
    print(f"   🎯 类型: {', '.join(event_types)}")
    if args.window:
        print(f"   🪟 目标窗口: {args.window}")
    
    response = input("\n确认开始回放? (y/N): ").strip().lower()
    if response != 'y':
        print("❌ 回放已取消")
        return
    
    # 倒计时
    for i in range(3, 0, -1):
        print(f"⏰ {i}秒后开始...")
        time.sleep(1)
    
    # 开始回放
    replayer.replay_events(
        event_types=event_types,
        skip_mouse_moves=not args.include_mouse_moves
    )

if __name__ == "__main__":
    main()
